package com.hserver.docker.service.impl;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.command.InitializeSwarmCmd;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.exec.RemoveSwarmNodeCmdExec;
import com.hserver.docker.bean.Deploy;
import com.hserver.docker.service.DeployService;
import com.hserver.docker.service.SwarmService;
import com.hserver.docker.utils.DockerUtil;
import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hxm
 */
@Bean
public class SwarmServiceImpl implements SwarmService {

    @Autowired
    private DeployService deployService;

    @Override
    public void updateSwarmNode(String id, SwarmNodeAvailability type) {
        DockerClient docker = DockerUtil.getDocker();
        try {
            List<SwarmNode> exec = docker.listSwarmNodesCmd().exec();
            for (SwarmNode swarmNode : exec) {
                if (swarmNode.getId().equals(id)) {
                    SwarmNodeSpec swarmNodeSpec = swarmNode.getSpec().withAvailability(type);
                    docker.updateSwarmNodeCmd().withSwarmNodeId(swarmNode.getId()).withVersion(swarmNode.getVersion().getIndex())
                            .withSwarmNodeSpec(swarmNodeSpec).exec();
                }
            }
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<Service> listSwarmService() {
        DockerClient docker = DockerUtil.getDocker();
        try {
            return docker.listServicesCmd().exec();
        } catch (Exception e) {
            return new ArrayList<>();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<SwarmNode> listSwarm() {
        DockerClient docker = DockerUtil.getDocker();
        try {
            return docker.listSwarmNodesCmd().exec();
        } catch (Exception e) {
            return new ArrayList<>();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Swarm checkSwarm() {
        DockerClient docker = DockerUtil.getDocker();
        try {
            return docker.inspectSwarmCmd().exec();
        } catch (Throwable e) {
            return null;
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public String addSwarm(String address1, String address2) {
        DockerClient docker = DockerUtil.getDocker(address2);
        try {
            try {
                //先离开节点
                docker.leaveSwarmCmd()
                        .withForceEnabled(true)
                        .exec();
            } catch (Throwable ignored) {
            }
            //在加入新的
            SwarmJoinTokens tokens = checkSwarm().getJoinTokens();
            List<String> name = new ArrayList<>();
            name.add(address1);
            docker.joinSwarmCmd()
                    .withRemoteAddrs(name)
                    .withJoinToken(tokens.getWorker())
                    .exec();
            Info info = docker.infoCmd().exec();
            System.out.println(info);
        } catch (Exception e) {
            return e.getMessage();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public String initSwarm(String address) {
        DockerClient docker = DockerUtil.getDocker();
        try {
            SwarmSpec swarmSpec = new SwarmSpec();
            InitializeSwarmCmd initializeSwarmCmd = docker.initializeSwarmCmd(swarmSpec);
            if (address != null && address.trim().length() > 0) {
                initializeSwarmCmd.withListenAddr(address);
            }
            initializeSwarmCmd.exec();
        } catch (Exception e) {
            return e.getMessage();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public void disbandCluster() {
        DockerClient docker = DockerUtil.getDocker();
        try {
            docker.leaveSwarmCmd().withForceEnabled(true).exec();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void removeService(String service) {
        List<Deploy> list = deployService.getList();
        for (Deploy deploy : list) {
            if (service.equals(deploy.getServiceId())) {
                deploy.setServiceId(null);
                deployService.update(deploy);
            }
        }
        DockerClient docker = DockerUtil.getDocker();
        try {
            docker.removeServiceCmd(service).exec();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void removeNode(String url) {
        DockerClient docker = DockerUtil.getDocker(url);
        try {
            docker.leaveSwarmCmd().withForceEnabled(true).exec();
        } finally {
            try {
                docker.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
